/*
 * @Author: Wanko
 * @Date: 2024-04-04 18:41:43
 * @LastEditors: Wanko
 * @LastEditTime: 2024-07-01 11:41:17
 * @Description:
 */
const User = require('../models/users')
const { response } = require('../utils/Response')
const { CODES_NAME } = require('../utils/constant.js')
const { signToken, signRefreshToken } = require('../middleware/auth.js')
const Card = require('../models/card')
const bcrypt = require('bcryptjs')
const md5 = require('md5')
class UsersCtl {
  async find(ctx) {
    const users = await User.find()
    response(ctx, users)
  }
  async findById(ctx) {
    const user = await User.findById(ctx.params.id)
    if (!user) return response(ctx, CODES_NAME.USER_NOT_EXIST)
    response(ctx, user)
  }
  async create(ctx, next) {
    ctx.verifyParams({
      username: 'string',
      password: 'string'
    })
    let { username, password, code} = ctx.request.body

    if(!code) return response(ctx, CODES_NAME.REGISTER_CODE)

    if(code !== '1107') return response(ctx, CODES_NAME.REGISTER_CODE_ERROR)

    const hasUser = await User.findOne({ username })

    if (hasUser) return response(ctx, CODES_NAME.USER_EXIST)

    // const hashPassword = await bcrypt.hash(password, 10)

    const data = {
      username,
      password
    }

    const user = await new User(data).save()

    await next({
      username,
      password
    })
    // response(ctx, user)
  }
  async update(ctx) {
    console.log(ctx.params.id, ctx.request.body)
    const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body, {
      new: true
    })
    if (!user) return response(ctx, CODES_NAME.USER_NOT_EXIST)
    response(ctx)
  }
  async del(ctx) {
    const user = await User.findByIdAndDelete(ctx.params.id)
    if (!user) return response(ctx, CODES_NAME.USER_NOT_EXIST)
    response(ctx)
  }

  async login(ctx) {
    ctx.verifyParams({
      username: 'string',
      password: 'string'
    })
    const user = await User.findOne(ctx.request.body)
    if (!user) return response(ctx, CODES_NAME.USER_PASSWORD_ERROR)
    const { _id, username } = user
    const token = signToken({ _id, username })
    const refreshToken = signRefreshToken({ _id, username })

    const data = {
      user,
      token,
      refreshToken
    }
    response(ctx, data)
  }

  async resetpwd(ctx) {
    const { _id } = ctx.state.user

    await User.findByIdAndUpdate(_id, { password: md5(ctx.request.body.password) })
    
    response(ctx)
  }

  async refresh(ctx) {
    const { _id, username } = ctx.state.user

    const token = signToken({ _id, username })
    const refreshToken = signRefreshToken({ _id, username })

    response(ctx, {
      token,
      refreshToken
    })
  }

  async likes(ctx) {
    await findList(ctx, 'like_cards')
  }

  async cards(ctx) {
    const page = parseInt(ctx.query.page) || 1
    const size = parseInt(ctx.query.size) || 20
    const skip = (page - 1) * size

    let cards = await Card.find({ owner: ctx.params.id })
      .populate('owner')
      .sort({ is_top: -1, createTime: -1 })
      .skip(skip)
      .limit(size)

    if (ctx.state.user) {
      const me = await User.findById(ctx.state.user._id).select('+like_cards+collection_cards')

      const { collection_cards, like_cards } = me

      cards = cards.map((card) => ({
        ...card.toObject(),
        is_liked: like_cards.includes(card._id) ? true : false,
        is_collected: collection_cards.includes(card._id) ? true : false
      }))
    }

    response(ctx, cards)
  }

  async collections(ctx) {
    await findList(ctx, 'collection_cards')
  }
}

const findList = async (ctx, name) => {
  const page = parseInt(ctx.query.page) || 1
  const size = parseInt(ctx.query.size) || 10
  const skip = (page - 1) * size
  const user = await User.findById(ctx.params.id)
    .select(`+${name}`)
    .populate({
      path: name,
      options: {
        sort: { createTime: -1 },
        skip,
        limit: size
      },
      populate: {
        path: 'owner', // 填充卡片的作者信息
      }
    })
  
  if (!user) return response(ctx, CODES_NAME.USER_NOT_EXIST)
  response(ctx, user[name])
}

module.exports = new UsersCtl()
